#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow){
    ui->setupUi(this);
        //QObject::connect(&mystack,SIGNAL(StackAdaptor::stackChanged()),this,SLOT(update()));
        print = 5;

        QObject::connect(ui->spinBox,SIGNAL(valueChanged(int)),this,SLOT(setPrint(int)));

        QObject::connect(ui->plusButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->minusButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->multiplyButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->divisionButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorCOSButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorSINButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorTANButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorEVALButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorSQRTButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorPOWbutton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorMODButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorFRACButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorSQRButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorINVButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorLOGButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorLNButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorSIGNButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorCUBEButton,SIGNAL(clicked()),this,SLOT(editLine()));


        QObject::connect(ui->num0Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num1Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num2Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num3Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num4Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num5Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num6Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num7Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num8Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num9Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->iButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->spaceButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->PointButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->quoteButton,SIGNAL(clicked()),this,SLOT(editLine()));


        QObject::connect(ui->swapButton,SIGNAL(clicked()),this,SLOT(stackSwap()));
        QObject::connect(ui->sumButton,SIGNAL(clicked()),this,SLOT(stackSum()));
        QObject::connect(ui->meanButton,SIGNAL(clicked()),this,SLOT(stackMean()));
        QObject::connect(ui->dupButton,SIGNAL(clicked()),this,SLOT(stackDup()));
        QObject::connect(ui->dropButton,SIGNAL(clicked()),this,SLOT(stackDrop()));

        QObject::connect(ui->enterButton,SIGNAL(clicked()),this,SLOT(operate()));
        QObject::connect(ui->delButton,SIGNAL(clicked()),this,SLOT(remove()));
        QObject::connect(ui->clearButton,SIGNAL(clicked()),this,SLOT(clear()));
        QObject::connect(ui->actionKeyboard,SIGNAL(toggled(bool)),this,SLOT(showdetails(bool)));

        QObject::connect(ui->actionRevert,SIGNAL(triggered()),this,SLOT(undo()));
        QObject::connect(ui->actionRedo,SIGNAL(triggered()),this,SLOT(redo()));

        if(Context::getInstance().getGrad()){
        ui->radioButton->setChecked(true);
        ui->radioButton_2->setChecked(false);
        }
        else{
        ui->radioButton->setChecked(false);
        ui->radioButton_2->setChecked(true);
        }

        bool key = Context::getInstance().getKey();
        ui->actionKeyboard->setChecked(key);
        showdetails(key);

        this->ui->UnaryOperatorKeyboardWidget->setVisible(key);
        this->ui->BinaryOperatorKeyboardFrame->setVisible(key);
        this->ui->MainKeyboardWidget->setVisible(key);

        for(int j=0;j<history.size();j++){
                std::string tmp = history[j].toStdString();
                std::vector<string> v = Calculator::parser(tmp);

                for(unsigned int i=0;i<v.size();i++)
                       ConstanteFactory::ConstantesFactory(v[i],mystack);
                update();

        }
}

void MainWindow::editLine(){
        QPushButton& tmp = static_cast<QPushButton&>(*QObject::sender());
        QString tmp1;
        if(tmp.text() == "_")
            tmp1 = " ";
        else if ((tmp.text() == "SIN" ||tmp.text() == "COS" || tmp.text() == "TAN") && ui->HcheckBox->isChecked())
            tmp1 = tmp.text() + "H";
        else
            tmp1 = tmp.text();

        ui->lineEdit_3->setText(ui->lineEdit_3->text()+tmp1);
        update();
 }

void MainWindow::remove(){
        QString tmp = ui->lineEdit_3->text();
        tmp.truncate(ui->lineEdit_3->text().size()-1);
        ui->lineEdit_3->setText(tmp);
 }

void MainWindow::redo(){
        std::vector<string> v = Calculator::parser(history.current().toStdString());
        if(history.next()){
           for(unsigned int i=0;i<v.size();i++)
                ConstanteFactory::ConstantesFactory(v[i],mystack);
            ui->lineEdit_3->setText(history.current());
            update();
        }
 }

void MainWindow::undo(){

        if(history.previous()){
        mystack.drop();
        ui->lineEdit_3->setText(history.current());
        if(history.current() == "+" ||history.current() == "-" ||history.current() == "*" ||
        history.current() == "/" ||history.current() == "^" ){
                history.previous();
                history.previous();
                redo();
                redo();
        }
        else if (history.current() == "INV" ||history.current() == "COS" ||history.current() == "SIN" ||
                history.current() == "SQRT" ||history.current() == "COSH" ||history.current() == "SINH"||
                history.current() == "LN"   ||history.current() == "LOG"){

                history.previous();
                redo();
        }

        update();
        }
 }

void MainWindow::clear(){
        ui->lineEdit_3->setText("");
        this->mystack.clear();
        this->history.clear();
        ui->textEdit->setText("");
 }

void MainWindow::showdetails(bool b){
        Context::getInstance().toogleKeyboard();
        this->ui->lineEdit_3->setReadOnly(b);
        this->ui->UnaryOperatorKeyboardWidget->setVisible(b);
        this->ui->BinaryOperatorKeyboardFrame->setVisible(b);
        this->ui->MainKeyboardWidget->setVisible(b);
 }

void MainWindow::operate(){
        std::vector<string> v = Calculator::parser(ui->lineEdit_3->text().toStdString());
        History tmp = history;
        StackAdaptor tmp2 = mystack;
        history.add(ui->lineEdit_3->text());
        if(ui->radioButton->isChecked())
                Context::getInstance().setGrad();
        else
                Context::getInstance().setDegree();
        try{
               for(unsigned int i=0;i<v.size();i++)
                      ConstanteFactory::ConstantesFactory(v[i],mystack);
        }
        catch(std::exception const& e)
           {
               ui->statusbar->showMessage(QString("ERREUR : ")+ e.what(),2000);
               history = tmp;
               mystack = tmp2;
           }
        ui->lineEdit_3->setText("");
        update();
 }

MainWindow::~MainWindow()
{
        Context::close();
        history.save();
    delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void MainWindow::stackSwap(){
        Constante *x,*y;
        x = mystack.top();
        mystack.drop();
        y = mystack.top();
        mystack.drop();
        mystack.swap(static_cast<Integer*>(x)->getVal()-1,static_cast<Integer*>(y)->getVal()-1);
        update();

}
void MainWindow::stackSum(){
        mystack.sum();
        update();
}
void MainWindow::stackMean(){
        mystack.mean();
        update();
}
void MainWindow::stackDup(){
        Integer x(0);
        mystack.add(Addition::apply(x,*mystack.top()));
        update();
}
void MainWindow::stackDrop(){
        mystack.drop();
        update();
}

    void MainWindow::update(){
        ui->textEdit->setText(QString(mystack.print(print).c_str()));
    }

void MainWindow::setPrint(int n){
        print = n;
        update();
}
